home *** CD-ROM | disk | FTP | other *** search
- {$D-,L-,Y-}
-
- UNIT DndLB; { Drag 'n Drop List Box }
-
- { :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
- Unit: DndLb
-
- Author: Ian Hayes
- Soft Systems Ltd.,
- London, UK
- Compuserve id: 100010,1415
-
- Description:
-
- A new listbox object for implementing the dragging of listbox
- items either to new positions in the current listbox or to
- other drag-friendly listboxes.
-
- Object name:
-
- TDndListBox
-
- Parent Object:
-
- TTwoWayListBox (refer to the TwoWayLb.Pas unit).
-
- Object data fields:
-
- DelOnTrfr : BOOLEAN;
-
- If set to TRUE then when an item is dragged to another
- listbox then it is deleted from the starting listbox.
-
- KeepSel : BOOLEAN;
-
- If set to TRUE then the dragged item retains its
- highlighted status, even if dragged to another listbox.
-
- DragExtent : TRect;
-
- The default rectangle area measured in absolute screen
- co-ordinates over which the mouse may drag a listbox item.
- By default this is set to the screen position equivalent
- of the owning dialog's client rectangle. You can set
- this to be a different rectangle based upon the
- position of other listboxes. Note that the values in this
- TRect are absolute screen co-ords. Its used to restrict
- mouse movement using 'ClipCursor()'.
-
- Object methods:
-
- CONSTRUCTOR Init(AParent : PWindowsObject;
- AnId : INTEGER;
- x,y,w,h : INTEGER;
- ADelOnTrfr : BOOLEAN);
-
- Creates a drag'n drop listbox object. If 'ADelOnTrfr' is
- set to TRUE then if an item is dragged to another listbox
- it is deleted from the starting listbox
-
- CONSTRUCTOR InitResource(AParent : PWindowsObject;
- AnId : INTEGER;
- ADelOnTrfr : BOOLEAN);
-
- Creates a drag'n drop listbox object to be associated
- with the 'AnId' resource. If 'ADelOnTrfr' is set to TRUE
- then if an item is dragged to another listbox it is deleted
- from the starting listbox
-
- FUNCTION GetClassName : PChar; VIRTUAL;
- PROCEDURE GetWindowClass(VAR AWndClass: TWndClass); VIRTUAL;
-
- Standard stuff.
-
- PROCEDURE SetupWindow; VIRTUAL;
-
- Sets the 'DragExtent' TRect to the absolute screen
- co-ord equivalents of the owning dialog's client area.
-
- FUNCTION GetItemFromY(Y: INTEGER) : INTEGER;
-
- Returns a listbox item position number from a client
- rectangle Y co-ordinate.
-
- PROCEDURE GetSelIndexRect(VAR ARect: TRect);
-
- Returns the rectangle position (in client co-ords) of
- the current listbox item.
-
- PROCEDURE wmChgLbItemPos(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_ChgLbItemPos;
-
- This message is sent by the same listbox to itself whenever a
- listbox item has been dragged to a new position. Msg.lParamlo
- is the item number of the item being dragged; Msg.lParamHi is
- the new position number - both numbers are base 0. If
- Msg.lParamHi is -1 then the item is being moved to the end of
- the list.
-
- PROCEDURE wmDelOnTrfr(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_DelOnTrfr;
-
- This message is sent by the listbox to itself whenever an item
- has been dragged outside to another listbox. By default this
- method will delete the dragged item from the starting lb if
- the 'DelOnTrfr' boolean flag is set to TRUE. Msg.wParam holds
- the item number.
-
- PROCEDURE wmGetDragExtent(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_GetDragExtent;
-
- Asks the receiving listbox for the current DragExtent
- TRect values. Msg.lParam holds a ptr to a TRect
- structure where the value is to be copied into. This allows
- the dialog window to enquire about the drag extent.
-
- PROCEDURE wmGetItemDragExtent(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_GetItemDragExtent;
-
- Used to find the mouse clipcursor TRectangle for
- a specified listbox item. Msg.wParam holds the listbox item
- index (base 0); whilst Msg.lParam holds a pointer to a TRect
- record. By default the message returns the standard DragExtent
- TRect values assigned within the SetupWindow method. By
- overriding this method you can set different drag extents
- for different listbox items.
-
- PROCEDURE wmLButtonDown(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_LButtonDown;
- PROCEDURE wmMouseMove(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_MouseMove;
- PROCEDURE wmLButtonUp(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_LButtonUp;
-
- Controls the drag'n drop processing.
-
- PROCEDURE wmSetDragExtent(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_SetDragExtent;
-
- Used to set the listbox drag extent. You could send
- this message from the owning dialog's SetupWindow method.
-
- PROCEDURE wmSetKeepSel(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_SetKeepSel;
-
- The 'KeepSel' object boolean data flag is used to
- determine whether the item selected hilite bar should
- be maintained on a listbox after an item has been
- dragged into another listbox. This message is used
- to update that flag. Msg.wParam holds a boolean value.
-
- PROCEDURE wmTrfrLbItem(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_TrfrLbItem;
-
- This message is received by a listbox when an item
- from another listbox has been dragged over and dropped
- onto this listbox. Msg.wParam holds the Other ListBox
- window handle (hWnd); Msg.lParamLo is the item number
- (base 0) of the other listbox item; Msg.lParamHi is
- the absolute screen Y position where the item was
- dropped. If the target listbox is able to accept the
- dropped item then it returns Msg.Result set to non zero.
- If the dropped item is not accepted then Msg.Result
- is set to zero.
-
- Dependancies:
-
- Currently this unit derives from another TListBox type
- called 'TTwoWayListBox' (refer to the TwoWayLb.pas unit).
- It also makes use of some special string handling functions
- (refer to the Strings1.Pas unit).
-
- Notes:
-
- At present this listbox object will only work with other
- drag'n drop listboxes of the same class name. You can see
- within the 'wmLButtonUp()' method that it checks for the
- class name of the 'other' control. You might want to amend
- this to expand the functionality.
-
- Also I can't seem to get the TDndListBox to work if the
- listbox is created via 'Init'. As I only ever use dialogs
- created with RW this is'nt a problem for me but somebody might
- want to research this problem.
-
- Please pass all feedback/bugs on this unit to me at my
- Compuserve id:
-
- Ian Hayes
- Soft Systems Ltd,
- London,UK
- Compuserve id: 100010,1415
-
- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: }
-
- INTERFACE
-
- { ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: }
-
- USES
-
- {$IFDEF Ver70}
- Objects,
- OWindows,
- ODialogs,
- {$ELSE}
- WObjects,
- {$ENDIF}
- WinProcs,
- WinTypes,
- Win31,
- TwoWayLb;
-
-
- { ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: }
-
- CONST
-
- { Drag & Drop List box level custom messages }
-
- wm_ChgLbItemPos = (wm_User+101);
- wm_TrfrLbItem = (wm_User+102);
- wm_GetDragExtent = (wm_User+103);
- wm_SetDragExtent = (wm_User+104);
- wm_DelOnTrfr = (wm_User+105);
- wm_SetKeepSel = (wm_User+106);
- wm_GetItemDragExtent = (wm_User+107);
- wm_LastDndCustMsg = wm_GetItemDragExtent;
-
- TYPE
-
- PDnDListBox = ^TDnDListBox;
-
- TDndListBox = OBJECT(TTwoWayListBox)
- { *** Data fields *** }
- DelOnTrfr : BOOLEAN; { delete items if dragged to another lb? }
- KeepSel : BOOLEAN; { if TRUE keep sel hilite on after trfr'ing
- item to another listbox }
- DragExtent : TRect; { extent of dragging area }
- { *** working vars used for drag drawing *** }
- DragDC : hDC; { used fro drag rectangle drawing }
- MoveWithin, { part of the dragging process }
- ButtonDown, { part of the dragging process }
- Dragging : BOOLEAN; { part of the dragging process }
- OrigRect, { original location of dragged item }
- DragRect : TRect; { rectangle being dragged }
- LastPos : TPoint; { last drag point }
- OldPen, { part of drag drawing }
- TheBlackPen : hPen; { part of drag drawing }
- OldROP2 : INTEGER; { part of drag drawing }
- { *** Methods *** }
- CONSTRUCTOR Init(AParent : PWindowsObject;
- AnId : INTEGER;
- x,y,w,h : INTEGER;
- ADelOnTrfr : BOOLEAN);
- CONSTRUCTOR InitResource(AParent : PWindowsObject;
- AnId : INTEGER;
- ADelOnTrfr : BOOLEAN);
- FUNCTION GetClassName : PChar; VIRTUAL;
- PROCEDURE GetWindowClass(VAR AWndClass: TWndClass); VIRTUAL;
- PROCEDURE SetupWindow; VIRTUAL;
- FUNCTION GetItemFromY(Y: INTEGER) : INTEGER;
- PROCEDURE GetSelIndexRect(VAR ARect: TRect);
- PROCEDURE wmChgLbItemPos(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_ChgLbItemPos;
- PROCEDURE wmDelOnTrfr(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_DelOnTrfr;
- PROCEDURE wmGetDragExtent(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_GetDragExtent;
- PROCEDURE wmGetItemDragExtent(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_GetItemDragExtent;
- PROCEDURE wmLButtonDown(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_LButtonDown;
- PROCEDURE wmMouseMove(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_MouseMove;
- PROCEDURE wmLButtonUp(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_LButtonUp;
- PROCEDURE wmSetDragExtent(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_SetDragExtent;
- PROCEDURE wmSetKeepSel(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_SetKeepSel;
- PROCEDURE wmTrfrLbItem(VAR Msg: TMessage);
- VIRTUAL wm_First + wm_TrfrLbItem;
- END;
-
- { ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: }
-
- IMPLEMENTATION
-
- { ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: }
-
- USES
-
- BWCC,
- Strings,
- Strings1;
-
- { ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: }
-
- { Description :
-
- As per normal listbox Init except for the 'ADelOnTrfr' flag. If the
- latter is passed as TRUE then when an item is dragged to another
- listbox it is deleted from its start listbox. }
-
- CONSTRUCTOR TDndListBox.Init(AParent : PWindowsObject;
- AnId : INTEGER;
- x,y,w,h : INTEGER;
- ADelOnTrfr : BOOLEAN);
- BEGIN
- INHERITED Init(AParent,AnId,x,y,w,h);
- ButtonDown := FALSE;
- DelOnTrfr := ADelOnTrfr;
- KeepSel := FALSE;
- END;
-
- { ----------------------------------------------------------------------- }
-
- { Description :
-
- As per normal listbox 'InitResource' except for the 'ADelOnTrfr' flag.
- If the latter is passed as TRUE then when an item is dragged to another
- listbox it is deleted from its start listbox. }
-
- CONSTRUCTOR TDndListBox.InitResource(AParent : PWindowsObject;
- AnId : INTEGER;
- ADelOnTrfr : BOOLEAN);
- BEGIN
- INHERITED InitResource(AParent,AnId);
- ButtonDown := FALSE;
- DelOnTrfr := ADelOnTrfr;
- KeepSel := FALSE;
- END;
-
- { ----------------------------------------------------------------------- }
-
- FUNCTION TDndListBox.GetClassName : PChar;
- BEGIN
- GetClassName := 'DndListBox';
- END;
-
- { ----------------------------------------------------------------------- }
-
- PROCEDURE TDndListBox.GetWindowClass(VAR AWndClass: TWndClass);
- BEGIN
- INHERITED GetWindowClass(AWndClass);
- END;
-
- { ----------------------------------------------------------------------- }
-
- PROCEDURE TDndListBox.SetupWindow;
- VAR
- ATRect : TRect;
- ATPt : TPoint;
- BEGIN
- INHERITED SetupWindow;
- { By default set the drag extent rectangle to be the screen area
- covered by the parent dialog client rectangle }
- GetClientRect(Parent^.hWindow,ATRect);
- ATPt.X := ATRect.Left;
- ATPt.Y := ATRect.Top;
- ClientToScreen(Parent^.hWindow,ATPt);
- DragExtent.Left := ATPt.X;
- DragExtent.Top := ATPt.Y;
- ATPt.X := ATRect.Right;
- ATPt.Y := ATRect.Bottom;
- ClientToScreen(Parent^.hWindow,ATPt);
- DragExtent.Right := ATPt.X;
- DragExtent.Bottom := ATPt.Y;
- END;
-
- { ----------------------------------------------------------------------- }
-
- { Description:
-
- Returns the listbox item number from a listbox client window
- co-ordinate Y value. }
-
- FUNCTION TDndListBox.GetItemFromY(Y: INTEGER) : INTEGER;
- VAR
- ItemHt,FromTop,TopItem: INTEGER;
- BEGIN
- ItemHt := SendMessage(hWindow,lb_GetItemHeight,WORD(GetSelIndex),0);
- FromTop := Y DIV ItemHt;
- TopItem := SendMessage(hWindow,lb_GetTopIndex,0,0);
- GetItemFromY := TopItem + FromTop;
- END;
-
- { ----------------------------------------------------------------------- }
-
- { Description:
-
- Returns the client window TRect position of the current listbox item. }
-
- PROCEDURE TDndListBox.GetSelIndexRect(VAR ARect: TRect);
- BEGIN
- SendMessage(hWindow,lb_GetItemRect,GetSelIndex,LONGINT(@ARect))
- END;
-
- { ----------------------------------------------------------------------- }
-
- { Custom message: This message is sent by the same listbox to itself
- whenever a listbox item has been dragged to a new
- position. Msg.lParamlo is the item number of the
- item being dragged; Msg.lParamHi is the new position
- number - both numbers are base 0. If Msg.lParamHi is
- -1 then the item is being moved to the end of the
- list. }
-
- PROCEDURE TDndListBox.wmChgLbItemPos(VAR Msg: TMessage);
- VAR
- ErrCode,L,StartItem,TargetItem : INTEGER;
- AStr : PChar;
- BEGIN
- StartItem := INTEGER(Msg.lParamLo);
- TargetItem := INTEGER(Msg.lParamHi);
- L := GetStringLen(StartItem)+1;
- GetMem(AStr,L);
- ErrCode := GetSelString(AStr,L);
- ErrCode := DeleteString(StartItem);
- UpdateWindow(hWindow);
- IF TargetItem = -1 THEN
- ErrCode := InsertString(AStr,-1)
- ELSE
- BEGIN
- IF TargetItem > StartItem THEN
- ErrCode := InsertString(AStr,TargetItem-1)
- ELSE
- ErrCode := InsertString(AStr,TargetItem);
- END;
- ErrCode := SetSelString(AStr,0);
- FreeMem(AStr,L);
- END;
-
- { ----------------------------------------------------------------------- }
-
- { Custom message: This message is sent by the listbox to itself
- whenever an item has been dragged outside to
- another listbox. By default this method will
- delete the dragged item from the starting lb if
- the 'DelOnTrfr' boolean flag is set to TRUE.
- Msg.wParam holds the item number. }
-
- PROCEDURE TDndListBox.wmDelOnTrfr(VAR Msg: TMessage);
- VAR
- SelIdx : INTEGER;
- BEGIN
- IF DelOnTrfr THEN
- BEGIN
- SelIdx := Msg.wParam;
- DeleteString(SelIdx);
- IF (GetCount > 0) AND KeepSel THEN
- BEGIN
- IF SelIdx >= GetCount THEN
- SetSelIndex(GetCount-1)
- ELSE
- SetSelIndex(SelIdx)
- END
- END
- END;
-
- { ----------------------------------------------------------------------- }
-
- { Custom message: Asks the receiving listbox for the current DragExtent
- TRect values. Msg.lParam holds a ptr to a TRect
- structure where the value is to be copied into. }
-
- PROCEDURE TDndListBox.wmGetDragExtent(VAR Msg: TMessage);
- BEGIN
- MOVE(DragExtent,POINTER(Msg.lParam)^,SIZEOF(DragExtent));
- END;
-
- { ----------------------------------------------------------------------- }
-
- { Custom message: used to find the mouse clipcursor TRectangle for
- a specified listbox item. Msg.wParam holds the
- listbox item index (base 0); whilst Msg.lParam
- holds a pointer to a TRect record. By default
- the message returns the standard DragExtent
- TRect values assigned within the SetupWindow
- method. }
-
- PROCEDURE TDndListBox.wmGetItemDragExtent(VAR Msg: TMessage);
- VAR
- ATRect : PRect;
- BEGIN
- MOVE(DragExtent,POINTER(Msg.lParam)^,SIZEOF(DragExtent));
- END;
-
- { ----------------------------------------------------------------------- }
-
- PROCEDURE TDndListBox.wmLButtonDown(VAR Msg: TMessage);
- VAR
- TargetItem: INTEGER;
- ClipTRect : TRect;
- BEGIN
- IF (NOT ButtonDown) THEN
- BEGIN
- { store mouse Pos }
- LastPos.X := Msg.lParamLo;
- LastPos.Y := Msg.lParamHi;
- { update sel idx based on mouse pt }
- TargetItem := GetItemFromY(Msg.lParamHi);
- IF TargetItem <= (GetCount-1) THEN
- BEGIN
- SetSelIndex(TargetItem);
- GetSelIndexRect(OrigRect);
- MOVE(OrigRect,DragRect,SIZEOF(OrigRect));
- IF PtInRect(DragRect,LastPos) THEN
- BEGIN
- ButtonDown := TRUE;
- { restrict cursor movement to the ClipTRect screen area }
- SendMessage(hWindow,
- wm_GetItemDragExtent,
- TargetItem,
- LONGINT(@ClipTRect));
- ClipCursor(@ClipTRect);
- { restrict mouse messages to this window }
- SetCapture(hWindow);
- { obtain window's DC }
- DragDC := GetDC(hWindow);
- Dragging := FALSE;
- { set device context }
- TheBlackPen := GetStockObject(Black_Pen);
- OldPen := SelectObject(DragDC,TheBlackPen);
- OldROP2 := SetROP2(DragDC,R2_NotXorPen);
- END
- END
- END;
- DefWndProc(Msg);
- END;
-
- { ----------------------------------------------------------------------- }
-
- PROCEDURE TDndListBox.wmMouseMove(VAR Msg: TMessage);
- VAR
- NewPt : TPoint;
- BEGIN
- IF ButtonDown THEN
- BEGIN
- { draw reactangle }
- IF Dragging THEN
- BEGIN
- WITH DragRect DO
- Rectangle(DragDC,Left,Top,Right,Bottom);
- END;
- Dragging := TRUE;
- MOVE(Msg.lParam,NewPt,SIZEOF(NewPt));
- { offset rectangle pos }
- OffSetRect(DragRect,
- NewPt.X - LastPos.X,
- NewPt.Y - LastPos.Y);
- { draw rectangle }
- WITH DragRect DO
- Rectangle(DragDC,Left,Top,Right,Bottom);
- { store mouse Pos }
- MOVE(NewPt,LastPos,SIZEOF(NewPt));
- END
- END;
-
- { ----------------------------------------------------------------------- }
-
- PROCEDURE TDndListBox.wmLButtonUp(VAR Msg: TMessage);
- VAR
- CRect : TRect;
- ATPt : TPoint;
- ScreenY,SelIdx,TargetIdx : INTEGER;
- OtherClassName : ARRAY[0..80] OF CHAR;
- OtherWnd : hWnd;
- OtherCtrl : PWindowsObject;
- MsgRes : LONGINT;
-
- { ++++++++++++++++++++++++++++++++++++++++++++++++++ }
-
- FUNCTION MatchWnd(AWnd: PWindowsObject) : BOOLEAN; FAR;
- BEGIN
- MatchWnd := ( AWnd^.hWindow = OtherWnd );
- END;
-
- { ++++++++++++++++++++++++++++++++++++++++++++++++++ }
-
- BEGIN
- IF ButtonDown THEN
- BEGIN
- WITH DragRect DO
- Rectangle(DragDC,Left,Top,Right,Bottom);
- { restore DC }
- SelectObject(DragDC,OldPen);
- SetROP2(DragDC,OldROP2);
- ReleaseDC(hWindow,DragDC);
- { reset flags }
- ReleaseCapture;
- { restore cursor clip region to full screen }
- ClipCursor(NIL);
- GetClientRect(hWindow,CRect);
- { is the end drag position within the listbox?}
- IF Dragging THEN
- BEGIN
- { is it within the starting listbox? }
- IF PtInRect(CRect,TPoint(Msg.lParam)) THEN
- BEGIN
- { stay within starting listbox item rectangle? }
- IF (NOT PtInRect(OrigRect,TPoint(Msg.lParam)))
- AND (GetCount > 1) THEN
- BEGIN
- TargetIdx := GetItemFromY(Msg.lParamHi);
- IF TargetIdx > GetCount THEN
- TargetIdx := -1;
- SelIdx := GetSelIndex;
- SendMessage(hWindow,
- wm_ChgLbItemPos,
- 0,
- MakeLong(WORD(SelIdx),WORD(TargetIdx)));
- END
- END
- ELSE { dragged outside of starting listbox }
- BEGIN
- { convert end pt to parent window client coords }
- ATPt.X := TPoint(Msg.lParam).X;
- ATPt.Y := TPoint(Msg.lParam).Y;
- ClientToScreen(hWindow,ATPt);
- ScreenY := ATPt.Y;
- ScreenToClient(Parent^.hWindow,ATPt);
- OtherWnd := ChildWindowFromPoint(Parent^.hWindow,ATPt);
- { is it outside all other controls or part of start window? }
- IF (OtherWnd = Parent^.hWindow) OR (OtherWnd = hWindow) THEN
- MessageBeep(0)
- ELSE
- BEGIN
- { Get OtherWnd class name }
- OtherCtrl := Parent^.FirstThat(@MatchWnd);
- IF (OtherCtrl = NIL) THEN
- MessageBeep(0)
- ELSE
- BEGIN
- StrCopy(OtherClassName,OtherCtrl^.GetClassName);
- IF SafeStrIComp(OtherClassName,'DndListBox') <> 0 THEN
- MessageBeep(0)
- ELSE
- BEGIN
- SelIdx := GetSelIndex;
- MsgRes := SendMessage(OtherWnd,
- wm_TrfrLbItem,
- WORD(hWindow),
- MakeLong(WORD(SelIdx),WORD(ScreenY)));
- { delete the item from the starting lb }
- IF MsgRes <> 0 THEN
- SendMessage(hWindow,
- wm_DelOnTrfr,
- WORD(SelIdx),
- 0);
- END
- END
- END
- END
- END;
- ButtonDown := FALSE;
- Dragging := FALSE;
- END;
- DefWndProc(Msg);
- END;
-
- { ----------------------------------------------------------------------- }
-
- { Custom message: Sent to the listbox - usually by the owning dialog
- window - to set the rectangle over which the item
- can be dragged. Msg.lParam holds a ptr to a TRect
- structure. The TRect structure is presumed to hold
- absolute screen coords. The TRect is used to update
- the DragExtent object data field, which in turn is
- used as a parameter for the 'ClipCursor()' function
- within the wmLButtonDown method. }
-
- PROCEDURE TDndListBox.wmSetDragExtent(VAR Msg: TMessage);
- BEGIN
- MOVE(POINTER(Msg.lParam)^,DragExtent,SIZEOF(DragExtent));
- END;
-
- { ----------------------------------------------------------------------- }
-
- { Custom message: The 'KeepSel' object boolean data flag is used to
- determine whether the item selected hilite bar should
- be maintained on a listbox after an item has been
- dragged into another listbox. This message is used
- to update that flag. Msg.wParam holds a boolean
- value. }
-
- PROCEDURE TDndListBox.wmSetKeepSel(VAR Msg: TMessage);
- BEGIN
- KeepSel := BOOLEAN(Msg.wParam);
- END;
-
- { ----------------------------------------------------------------------- }
-
- { Custom message: This message is received by a listbox when an item
- from another listbox has been dragged over and dropped
- onto this listbox. Msg.wParam holds the Other ListBox
- window handle (hWnd); Msg.lParamLo is the item number
- (base 0) of the other listbox item; Msg.lParamHi is
- the absolute screen Y position where the item was
- dropped. If the target listbox is able to accept the
- dropped item then it returns Msg.Result set to non zero.
- If the dropped item is not accepted then Msg.Result
- is set to zero. }
-
- PROCEDURE TDndListBox.wmTrfrLbItem(VAR Msg: TMessage);
- VAR
- OtherLbWnd : hWnd;
- L,TargetItem,StartItem : INTEGER;
- AStr : PChar;
- BEGIN
- OtherLbWnd := hWnd(Msg.wParam);
- StartItem := INTEGER(Msg.lParamLo);
- { find listbox y position }
- ScreenToClient(HWindow,TPoint(Msg.lParam));
- TargetItem := GetItemFromY(Msg.lParamHi);
- IF TargetItem > (GetCount-1) THEN
- TargetItem := -1;
- { get the other listbox item string }
- L := SendMessage(OtherLbWnd,lb_GetTextLen,StartItem,0) + 1;
- GetMem(AStr,L);
- SendMessage(OtherLbWnd,lb_GetText,StartItem,LONGINT(AStr));
- { insert item into listbox }
- InsertString(AStr,TargetItem);
- { give the new item the focus }
- IF TargetItem = -1 THEN
- SetSelString(AStr,GetCount-2)
- ELSE
- SetSelString(AStr,TargetItem-1);
- FreeMem(AStr,L);
- Msg.Result := 1;
- END;
-
- { ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: }
-
- BEGIN
-
- END.